package vip.xiaonuo.invoice.modular.service.impl;

import vip.xiaonuo.invoice.core.enums.invoice.InvoicePlatformEnum;
import vip.xiaonuo.invoice.core.enums.invoice.InvoiceStatusEnum;
import java.util.Objects;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Service;
import vip.xiaonuo.invoice.core.adapter.InvoicePlatformAdapter;
import vip.xiaonuo.invoice.core.adapter.dto.request.InvoiceRedeliverRequestDto;
import vip.xiaonuo.invoice.core.adapter.dto.request.InvoiceRequestDtoOfShuZu;
import vip.xiaonuo.invoice.core.adapter.dto.request.RedInvoiceRequestDtoOfShuZu;
import vip.xiaonuo.invoice.core.adapter.dto.result.*;
import vip.xiaonuo.invoice.core.enums.invoice.InvoiceErrorCodeEnum;
import vip.xiaonuo.invoice.core.enums.invoice.InvoicePlatformEnum;
import vip.xiaonuo.invoice.core.enums.invoice.InvoiceStatusEnum;
import vip.xiaonuo.invoice.core.exception.InvoiceException;
import vip.xiaonuo.invoice.core.factory.InvoicePlatformAdapterFactory;
import vip.xiaonuo.invoice.core.util.BizUtil;
import vip.xiaonuo.invoice.core.util.HttpUtil;
import vip.xiaonuo.invoice.core.util.MathUtil;
import vip.xiaonuo.invoice.modular.param.*;
import vip.xiaonuo.invoice.modular.service.InvoiceService;
import vip.xiaonuo.invoice.modular.system.item.entity.IvoItem;
import vip.xiaonuo.invoice.modular.system.item.mapper.IvoItemMapper;
import vip.xiaonuo.invoice.modular.system.item.service.IvoItemService;
import vip.xiaonuo.invoice.modular.system.ivorecord.entity.IvoRecord;
import vip.xiaonuo.invoice.modular.system.ivorecord.mapper.IvoRecordMapper;
import vip.xiaonuo.invoice.modular.system.ivorecord.service.IvoRecordService;
import vip.xiaonuo.invoice.modular.system.redrecord.entity.RedRecord;
import vip.xiaonuo.invoice.modular.system.redrecord.service.RedRecordService;
import vip.xiaonuo.invoice.modular.system.sellerinfo.entity.IvoSellerInfo;
import vip.xiaonuo.invoice.modular.system.sellerinfo.mapper.IvoSellerInfoMapper;
import vip.xiaonuo.invoice.modular.vo.*;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * 发票服务实现类
 *
 * @author AI Assistant
 */
// 添加Logger导入和实例定义


// 首先，在类顶部添加RedRecordService的注入
@Service
public class InvoiceServiceImpl implements InvoiceService {

    private static final Logger log = LoggerFactory.getLogger(InvoiceServiceImpl.class);

    // 添加Jackson的ObjectMapper实例
    private static final ObjectMapper objectMapper = new ObjectMapper();
    // 最大重试次数
    private static final int MAX_RETRY_COUNT = 3;
    // 重试间隔（毫秒）
    private static final long RETRY_INTERVAL = 30000L; // 30秒
    private static final String ALLOWED_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    // 添加ThreadPoolTaskScheduler用于异步重试
    private static final int RANDOM_STRING_LENGTH = 8;
    private static final Random RANDOM = new Random();
    // 使用ConcurrentHashMap存储每个发票ID的重试次数
    private final Map<String, AtomicInteger> retryCounterMap = new ConcurrentHashMap<>();
    @Resource
    private ThreadPoolTaskScheduler taskScheduler;
    @Autowired
    private IvoSellerInfoMapper ivoSellerInfoMapper;

    @Autowired
    private IvoRecordMapper ivoRecordMapper;

    @Autowired
    private IvoItemMapper ivoItemMapper;

    @Resource
    private IvoRecordService ivoRecordService;

    @Resource
    private IvoItemService ivoItemService;

    @Resource
    private RedRecordService redRecordService;


    @Override
    public InvoiceSubmitResultVo createInvoice(InvoiceRequestParam param) {

        // 1. 参数校验
        InvoiceSubmitResultVo validationResult = validateParam(param);
        if (ObjectUtil.isNotEmpty(validationResult)) {
            return validationResult;
        }

        // 2. 根据销方税号查询抬头信息
        IvoSellerInfo sellerInfo = getSellerInfoByTaxNumber(param.getSellerTaxNumber());
        if (ObjectUtil.isEmpty(sellerInfo)) {
            InvoiceSubmitResultDto result = new InvoiceSubmitResultDto();
            return buildErrorResult(result, InvoiceErrorCodeEnum.SELLER_INFO_NOT_FOUND);
        }

        // 3. 根据销方税号获取开票平台
        InvoicePlatformEnum platform = selectInvoicePlatform(sellerInfo);

        // 4. 从工厂获取对应的平台适配器
        InvoicePlatformAdapter invoiceInstance = InvoicePlatformAdapterFactory.getAdapterByEnum(platform);

        // 5. 转换参数：将InvoiceRequestParam转换为InvoiceRequestDto
        // todo 根据对应的平台转化为应对参数
        InvoiceRequestDtoOfShuZu requestDto = convertToShuZuDto(param, sellerInfo);

        // 6. 调用适配器进行开票
        InvoiceSubmitResultDto submitResultDto = invoiceInstance.createInvoice(requestDto);
        InvoiceSubmitResultVo invoiceSubmitResultVo = BeanUtil.copyProperties(submitResultDto, InvoiceSubmitResultVo.class);
        if (submitResultDto.isSuccess()) {
            // 7. 保存开票结果
            String invoiceTraceId = saveInvoiceRecordAndItem(param, sellerInfo, requestDto);
            invoiceSubmitResultVo.setInvoiceTraceId(invoiceTraceId);
        }
        // 8. 构建并返回结果
        return invoiceSubmitResultVo;
    }

    @Override
    public InvoiceSubmitResultVo reCreateInvoice(ReInvoiceRequestParam reInvoiceRequestParam) {
        // 参数校验
        if (reInvoiceRequestParam == null || StringUtils.isBlank(reInvoiceRequestParam.getInvoiceTraceId())) {
            return buildErrorResult(new InvoiceSubmitResultDto(), InvoiceErrorCodeEnum.PARAM_ERROR);
        }

        // 查询原发票记录
        IvoRecord originalRecord = ivoRecordMapper.selectOne(new LambdaQueryWrapper<IvoRecord>()
                .eq(IvoRecord::getInvoiceTraceId, reInvoiceRequestParam.getInvoiceTraceId()));

        if (ObjectUtil.isEmpty(originalRecord)) {
            return buildErrorResult(new InvoiceSubmitResultDto(), InvoiceErrorCodeEnum.INVOICE_NOT_EXIST);
        }
        if ("1".equals(originalRecord.getInvoiceStatus())){
            return buildErrorResult(new InvoiceSubmitResultDto(), InvoiceErrorCodeEnum.INVOICE_NOT_EXIST);

        }
        // 获取平台适配器
        InvoicePlatformAdapter invoiceInstance = InvoicePlatformAdapterFactory.getAdapter(originalRecord.getPlatformCode());
        if (ObjectUtil.isEmpty(invoiceInstance)) {
            return buildErrorResult(new InvoiceSubmitResultDto(), InvoiceErrorCodeEnum.PLATFORM_ADAPTER_NOT_FOUND);
        }

        // 检查是否有待使用的请求数据
        String requestJson = originalRecord.getRequest();
        if (StringUtils.isBlank(requestJson)) {
            return buildErrorResult(new InvoiceSubmitResultDto(), InvoiceErrorCodeEnum.RECREATE_NO_REQUEST_DATA);
        }

        // 反序列化请求DTO
        InvoiceRequestDtoOfShuZu requestDto;
        try {
            requestDto = objectMapper.readValue(requestJson, InvoiceRequestDtoOfShuZu.class);
        } catch (Exception e) {
            log.error("反序列化请求DTO失败", e);
            return buildErrorResult(new InvoiceSubmitResultDto(), InvoiceErrorCodeEnum.RECREATE_DESERIALIZE_ERROR);
        }
        // 6. 调用适配器进行开票
        InvoiceSubmitResultDto submitResultDto = invoiceInstance.createInvoice(requestDto);
        InvoiceSubmitResultVo invoiceSubmitResultVo = BeanUtil.copyProperties(submitResultDto, InvoiceSubmitResultVo.class);
        if (submitResultDto.isSuccess()) {
            // 7. 更新重开次数
            try {
                // 获取当前重试次数（字符串类型），如果为空则设为"0"
                String currentRetryTimes = originalRecord.getRetryTimes().isEmpty() ? "0" : originalRecord.getRetryTimes();
                // 转换为整数加1后再转回字符串
                String newRetryTimes = String.valueOf(Integer.parseInt(currentRetryTimes) + 1);
                // 更新重试次数
                originalRecord.setRetryTimes(newRetryTimes);
                // 更新到数据库
                ivoRecordMapper.updateById(originalRecord);
                log.info("发票重开成功，invoiceTraceId: {}, 重开次数: {}", reInvoiceRequestParam.getInvoiceTraceId(), newRetryTimes);
            } catch (Exception e) {
                log.error("更新发票重开次数失败", e);
                // 更新失败不影响主流程
            }
            invoiceSubmitResultVo.setInvoiceTraceId(reInvoiceRequestParam.getInvoiceTraceId());
        }
        // 8. 构建并返回结果
        return invoiceSubmitResultVo;
    }

    public void queryAndUpdateInvoice() {
        // 1. 查询所有状态为0(开票中)且创建时间在10天内的发票记录
        LambdaQueryWrapper<IvoRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(IvoRecord::getInvoiceStatus, InvoiceStatusEnum.PROCESSING.getCode());
        // 添加时间限制：只查询创建时间在10天内的记录
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_MONTH, -10);
        Date tenDaysAgo = calendar.getTime();
        queryWrapper.ge(IvoRecord::getCreateTime, tenDaysAgo);
        List<IvoRecord> processingInvoices = ivoRecordService.list(queryWrapper);
        if (processingInvoices.isEmpty()) {
            log.info("查询并更新开票记录:没有需要处理的发票");
            //为空即没有需要更新的发票记录
            return;
        }
        // 5. 按平台分组处理这些发票
        Map<String, List<IvoRecord>> platformInvoicesMap = processingInvoices.stream()
                .collect(Collectors.groupingBy(IvoRecord::getPlatformCode));

        // 6. 处理各平台的发票查询逻辑
        List<IvoRecord> shuZuRecords = platformInvoicesMap.get(InvoicePlatformEnum.SHUZU.getCode());
        if (!ObjectUtil.isEmpty(shuZuRecords)) {
            processShuZuPlatformInvoices(shuZuRecords);
        }
        List<IvoRecord> nuonuoRecords = platformInvoicesMap.get(InvoicePlatformEnum.NUONUO.getCode());
        if (!ObjectUtil.isEmpty(nuonuoRecords)) {
            processNuonuoPlatformInvoices(nuonuoRecords);
        }
    }

    @Override
    public RedInvoiceSubmitResultVo createRedInvoice(RedInvoiceRequestParam redInvoiceRequestParam) {
        String invoiceTraceId = redInvoiceRequestParam.getInvoiceTraceId();
        log.info("开始执行发票冲红操作，发票ID: {}", invoiceTraceId);

        try {
            // 1. 根据发票ID查询发票记录
            LambdaQueryWrapper<IvoRecord> ivoRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
            ivoRecordLambdaQueryWrapper.eq(IvoRecord::getInvoiceTraceId, invoiceTraceId);
            IvoRecord ivoRecord = ivoRecordMapper.selectOne(ivoRecordLambdaQueryWrapper);
            if (ObjectUtil.isEmpty(ivoRecord)) {
                log.error("未找到发票记录，发票ID: {}", invoiceTraceId);
                throw new InvoiceException("未找到发票记录");
            }
            // 2. 根据销方税号查询抬头信息
            IvoSellerInfo sellerInfo = getSellerInfoByTaxNumber(ivoRecord.getSellerTaxNumber());
            if (ObjectUtil.isEmpty(sellerInfo)) {
                log.error("未查询到商户信息，发票ID: {}", invoiceTraceId);
                throw new InvoiceException("未找到商户信息");
            }
            // 2. 获取发票平台
            InvoicePlatformEnum platform = InvoicePlatformEnum.getByCode(ivoRecord.getPlatformCode());
            if (platform == null) {
                throw new InvoiceException("不支持的发票平台：" + ivoRecord.getPlatformCode());
            }

            // 3. 从工厂获取对应的平台适配器
            InvoicePlatformAdapter instance = InvoicePlatformAdapterFactory.getAdapterByEnum(platform);

            // 4. 创建冲红请求参数并将param转换为dto
            RedInvoiceRequestDtoOfShuZu redInvoiceRequestDto = convertToRedInvoiceDto(redInvoiceRequestParam, ivoRecord, sellerInfo);

            // 5. 调用适配器进行冲红
            RedInvoiceSubmitResultDto result = instance.createRedInvoice(redInvoiceRequestDto);

            // 6. 创建并设置返回结果对象
            RedInvoiceSubmitResultVo redInvoiceSubmitResultVo = new RedInvoiceSubmitResultVo();
            redInvoiceSubmitResultVo.setCode(result.getCode());
            redInvoiceSubmitResultVo.setDescription(result.getDescription());

            // 7. 处理冲红提交结果
            if (ObjectUtil.isNotEmpty(result) && result.isSuccess()) {
                log.info("冲红发票提交成功，原发票跟踪ID: {}, 红票请求单确认ID: {}",
                        invoiceTraceId, result.getRedInvoiceConfirmId());
                String redInvoiceTraceId = BizUtil.generateTraceId(sellerInfo.getSellerId());
                redInvoiceSubmitResultVo.setRedInvoiceTraceId(redInvoiceTraceId);

                // 创建红冲记录，使用专门的RedRecord实体类
                RedRecord redRecord = new RedRecord();

                // 设置红票信息确认单id和编号和追踪id
                redRecord.setRedInvoiceTraceId(redInvoiceTraceId);
                redRecord.setRedInvoiceConfirmId(result.getRedInvoiceConfirmId());
                redRecord.setRedInvoiceConfirmNo(result.getRedInvoiceConfirmNo());

                // 设置原发票信息
                redRecord.setSellerId(ivoRecord.getSellerId());
                redRecord.setOriginalInvoiceTraceId(invoiceTraceId);
                redRecord.setOriginalInvoiceNo(ivoRecord.getInvoiceNo());
                redRecord.setOriginalInvoiceTypeCode(ivoRecord.getInvoiceType());
                redRecord.setOriginalInvoiceDate(ivoRecord.getInvoiceDate());

                // 设置购方和销方信息
                redRecord.setBuyerName(ivoRecord.getBuyerName());
                redRecord.setBuyerTaxNumber(ivoRecord.getBuyerTaxNumber());
                redRecord.setSellerTaxNumber(ivoRecord.getSellerTaxNumber());
                redRecord.setSellerName(ivoRecord.getSellerName());

                // 设置冲红原因代码和申请来源
                String redReasonCode = ObjectUtil.isEmpty(redInvoiceRequestParam.getRedReasonCode()) ?
                        redInvoiceRequestParam.getRedReasonCode() : "01"; // 默认为开票有误
                redRecord.setRedReasonCode(redReasonCode);
                redRecord.setApplicationSource("0"); // 0-销方申请

                redRecord.setCallbackUrl(redInvoiceRequestParam.getCallbackUrl());

                // 设置平台信息和状态
                redRecord.setPlatformCode(ivoRecord.getPlatformCode());
                redRecord.setStatus("0"); // 0:处理中

                // 保存红冲记录
                redRecordService.save(redRecord);
                log.info("红冲记录保存成功，红票记录ID: {}", redRecord.getId());

            } else {
                String errorMsg = result.getDescription();
                log.error("冲红发票失败，发票ID: {}, 错误信息: {}", invoiceTraceId, errorMsg);
                throw new InvoiceException("冲红发票失败: " + errorMsg);
            }

            // 返回结果对象
            return redInvoiceSubmitResultVo;

        } catch (Exception e) {
            log.error("冲红发票发生异常: {}", e.getMessage(), e);
            // 创建错误结果对象
            RedInvoiceSubmitResultVo errorResult = new RedInvoiceSubmitResultVo();
            errorResult.setCode(InvoiceErrorCodeEnum.NONE_ERROR.getCode());
            errorResult.setDescription(e.getMessage());
            return errorResult;
        }
    }

    public void queryAndUpdateRedInvoice() {
        // 1. 查询所有状态为0(处理中)且创建时间在3天内的红票记录
        LambdaQueryWrapper<RedRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RedRecord::getStatus, "0"); // 状态为0表示处理中
        // 添加时间限制：只查询创建时间在3天内的记录
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_MONTH, -3);
        Date threeDaysAgo = calendar.getTime();
        queryWrapper.ge(RedRecord::getCreateTime, threeDaysAgo);
        List<RedRecord> allProcessingRedInvoices = redRecordService.list(queryWrapper);

        if (allProcessingRedInvoices.isEmpty()) {
            log.info("没有需要更新的红票记录");
            return;
        }
        Map<String, List<RedRecord>> platformInvoicesMap = allProcessingRedInvoices.stream()
                .collect(Collectors.groupingBy(RedRecord::getPlatformCode));
        // 2. 筛选出数族平台的订单
        List<RedRecord> shuZuRecords = platformInvoicesMap.get(InvoicePlatformEnum.SHUZU.getCode());
        // 3. 处理数族平台的红票记录
        if (ObjectUtil.isNotEmpty(shuZuRecords)) {
            processShuZuPlatformRedInvoices(shuZuRecords);
        }
        // 4. 处理其他平台的红票记录（如有）
    }

    @Override
    public RedeliverSubmitResultVo reDeliverInvoice(RedeliverRequestParam redeliverRequestParam) {
        String invoiceTraceId = redeliverRequestParam.getInvoiceTraceId();
        String email = redeliverRequestParam.getEmail();
        String phone = redeliverRequestParam.getPhone();
        log.info("执行发票重新交付，发票ID: {}", invoiceTraceId);

        try {
            // 1. 根据发票ID查询发票记录
            IvoRecord ivoRecord = ivoRecordMapper.selectOne(new LambdaQueryWrapper<IvoRecord>()
                    .eq(IvoRecord::getInvoiceTraceId, invoiceTraceId));
            if (ObjectUtil.isEmpty(ivoRecord)) {
                log.error("未找到发票记录，发票ID: {}", invoiceTraceId);
                throw new InvoiceException("未找到发票记录");
            }
            if (!InvoiceStatusEnum.SUCCESS.getCode().equals(ivoRecord.getInvoiceStatus())) {
                log.error("发票尚未开具，无法重新交付,发票ID: {}", invoiceTraceId);
                throw new InvoiceException("发票尚未开具,请稍后重试");
            }

            // 2. 根据销方税号查询抬头信息
            IvoSellerInfo sellerInfo = getSellerInfoByTaxNumber(ivoRecord.getSellerTaxNumber());
            if (ObjectUtil.isEmpty(sellerInfo)) {
                log.info("执行发票重新交付无法查询到抬头信息，发票ID: {}", invoiceTraceId);
                throw new InvoiceException("抬头信息有误,请联系管理人员");
            }

            // 3. 校验邮箱和手机号码 - 修改逻辑：只要有一个联系方式存在即可
            boolean hasEmail = !isEmpty(email) || !StringUtils.isEmpty(ivoRecord.getReceiveEmail());
            boolean hasPhone = !isEmpty(phone) || !StringUtils.isEmpty(ivoRecord.getReceivePhone());

            if (!hasEmail && !hasPhone) {
                throw new InvoiceException("邮箱和手机号码至少有一个不能为空");
            }

            // 4. 获取发票平台
            InvoicePlatformEnum platform = InvoicePlatformEnum.getByCode(ivoRecord.getPlatformCode());
            if (platform == null) {
                throw new InvoiceException("不支持的发票平台：" + ivoRecord.getPlatformCode());
            }

            // 5. 从工厂获取对应的平台适配器
            InvoicePlatformAdapter instance = InvoicePlatformAdapterFactory.getAdapterByEnum(platform);

            // 6. 创建重新交付请求参数
            InvoiceRedeliverRequestDto redeliverRequestDto = new InvoiceRedeliverRequestDto();
            redeliverRequestDto.setSellerId(sellerInfo.getSellerId());
            redeliverRequestDto.setInvoiceTraceId(invoiceTraceId);
            redeliverRequestDto.setInvoiceNo(ivoRecord.getInvoiceNo());
            redeliverRequestDto.setSellerTaxNumber(ivoRecord.getSellerTaxNumber());
            // 前端传来的email优先，为空时使用库表数据
            redeliverRequestDto.setEmail(isEmpty(email) ? ivoRecord.getReceiveEmail() : email);
            // 前端传来的phone优先，为空时使用库表数据
            redeliverRequestDto.setPhoneNumber(isEmpty(phone) ? ivoRecord.getReceivePhone() : phone);

            // 7. 调用适配器进行重新交付
            RedeliverResultDto result = instance.reDeliverInvoice(redeliverRequestDto);

            RedeliverSubmitResultVo redeliverSubmitResultVo = new RedeliverSubmitResultVo();
            // 8. 根据结果更新状态
            if (result.isSuccess()) {
                log.info("发票重新交付成功，发票ID: {}", invoiceTraceId);
                redeliverSubmitResultVo.setCode(InvoiceErrorCodeEnum.REDELIVER_SUCCESS.getCode());
                redeliverSubmitResultVo.setDescription(InvoiceErrorCodeEnum.REDELIVER_SUCCESS.getMsg());
            } else {
                log.error("发票重新交付失败，发票ID: {}", invoiceTraceId);
                redeliverSubmitResultVo.setCode(InvoiceErrorCodeEnum.REDELIVER_FAILED.getCode());
                redeliverSubmitResultVo.setDescription(result.getDescription());
            }

            return redeliverSubmitResultVo;
        } catch (InvoiceException e) {
            log.error("重新交付发票失败: {}", e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("重新交付发票发生异常: {}", e.getMessage(), e);
            throw new InvoiceException("重新交付发票失败");
        }
    }

    @Override
    public GetValidSubmitResultVo getValidCode(GetValidCodeRequestParam getValidCodeRequestParam) {
        // 2. 根据销方税号查询抬头信息
        IvoSellerInfo sellerInfo = getSellerInfoByTaxNumber(getValidCodeRequestParam.getSellerTaxNumber());
        if (ObjectUtil.isEmpty(sellerInfo)) {
            log.error("获取短信验证码失败,无法找到该税号对应商户,税号:{}", getValidCodeRequestParam.getSellerTaxNumber());
            throw new InvoiceException(InvoiceErrorCodeEnum.SELLER_INFO_NOT_FOUND.getCode(),
                    "无法找到该税号对应商户,税号:" + getValidCodeRequestParam.getSellerTaxNumber());
        }

        // 3. 根据销方税号获取开票平台
        InvoicePlatformEnum platform = selectInvoicePlatform(sellerInfo);

        // 4. 从工厂获取对应的平台适配器
        InvoicePlatformAdapter invoiceInstance = InvoicePlatformAdapterFactory.getAdapterByEnum(platform);

        GetValidSubmitResultDto validCode = invoiceInstance.getValidCode(sellerInfo.getSellerId());
        GetValidSubmitResultVo getValidSubmitResultVo = new GetValidSubmitResultVo();
        getValidSubmitResultVo.setCode(validCode.getCode());
        getValidSubmitResultVo.setDescription(validCode.getDescription());
        return getValidSubmitResultVo;
    }

    @Override
    public CommitValidSubmitResultVo commitValidCode(CommitValidCodeRequestParam commitValidCodeRequestParam) {
        // 2. 根据销方税号查询抬头信息
        IvoSellerInfo sellerInfo = getSellerInfoByTaxNumber(commitValidCodeRequestParam.getSellerTaxNumber());
        if (ObjectUtil.isEmpty(sellerInfo)) {
            log.error("获取短信验证码失败,无法找到该税号对应商户,税号:{}", commitValidCodeRequestParam.getSellerTaxNumber());
            throw new InvoiceException(InvoiceErrorCodeEnum.SELLER_INFO_NOT_FOUND.getCode(),
                    "无法找到该税号对应商户,税号:" + commitValidCodeRequestParam.getSellerTaxNumber());
        }

        // 3. 根据销方税号获取开票平台
        InvoicePlatformEnum platform = selectInvoicePlatform(sellerInfo);

        // 4. 从工厂获取对应的平台适配器
        InvoicePlatformAdapter invoiceInstance = InvoicePlatformAdapterFactory.getAdapterByEnum(platform);

        CommitValidSubmitResultDto resultVo = invoiceInstance.commitValidCode(sellerInfo.getSellerId(), commitValidCodeRequestParam.getValidCode());
        CommitValidSubmitResultVo commitValidSubmitResultVo = new CommitValidSubmitResultVo();
        commitValidSubmitResultVo.setCode(resultVo.getCode());
        commitValidSubmitResultVo.setDescription(resultVo.getDescription());
        return commitValidSubmitResultVo;
    }

    //----------------------------------------------

    /**
     * 将冲红请求参数转换为DTO对象
     */
    private RedInvoiceRequestDtoOfShuZu convertToRedInvoiceDto(RedInvoiceRequestParam redInvoiceRequestParam, IvoRecord ivoRecord, IvoSellerInfo sellerInfo) {
        RedInvoiceRequestDtoOfShuZu redInvoiceRequestDto = new RedInvoiceRequestDtoOfShuZu();
        redInvoiceRequestDto.setSellerId(sellerInfo.getSellerId());

        redInvoiceRequestDto.setYfphm(ivoRecord.getInvoiceNo()); // 原发票号码
        redInvoiceRequestDto.setXfsh(ivoRecord.getSellerTaxNumber()); // 销方税号
        redInvoiceRequestDto.setYfplxdm(ivoRecord.getInvoiceType()); // 原发票类型代码
        redInvoiceRequestDto.setYkprq(ivoRecord.getInvoiceDate()); // 原开票日期

        // 设置从param传入的冲红相关信息
        if (ObjectUtil.isNotEmpty(redInvoiceRequestParam.getRedReasonCode())) {
            redInvoiceRequestDto.setChyydm(redInvoiceRequestParam.getRedReasonCode()); // 冲红原因代码
        } else {
            redInvoiceRequestDto.setChyydm("01"); // 默认冲红原因代码，01表示开票有误
        }

        // 设置特定要素类型代码
        redInvoiceRequestDto.setTdyslxdm(ivoRecord.getSpecialTypeCode()); // 从原发票获取

        // 设置申请类型，目前仅支持销方申请
        redInvoiceRequestDto.setSqly("0"); // 申请类型，0-销方申请

        // 直接从IvoRecord获取含税金额和税额，并一次性完成负数转换和四舍五入
        String negativeWithoutTaxAmountStr = ivoRecord.getWithoutTaxAmount().negate().setScale(2, RoundingMode.HALF_UP).toString();
        String negativeTaxAmountStr = ivoRecord.getTaxAmount().negate().setScale(2, RoundingMode.HALF_UP).toString();
        // 设置合计金额和冲红金额
        redInvoiceRequestDto.setHzcxje(negativeWithoutTaxAmountStr);
        redInvoiceRequestDto.setHzcxse(negativeTaxAmountStr);

        // 检查是否同时传入了三个参数，如果部分传入则抛出异常
        boolean hasAmount = StringUtils.isNotBlank(redInvoiceRequestParam.getRedAmount());
        boolean hasTaxAmount = StringUtils.isNotBlank(redInvoiceRequestParam.getRedTaxAmount());
        boolean hasTaxRate = StringUtils.isNotBlank(redInvoiceRequestParam.getRedTaxRate());

        // 如果部分参数存在，部分不存在，则抛出异常
        if ((hasAmount || hasTaxAmount || hasTaxRate) && !(hasAmount && hasTaxAmount && hasTaxRate)) {
            throw new InvoiceException("若使用部分冲红,冲红金额、冲红税额、税率必须同时传入");
        }
        // 使用部分冲红 设置参数
        if (hasAmount) {
            // 1. 处理冲红金额
            BigDecimal redAmount = new BigDecimal(redInvoiceRequestParam.getRedAmount());
            redInvoiceRequestDto.setJe(redAmount.negate().setScale(2, RoundingMode.HALF_UP).toString());

            // 2. 处理冲红税额
            BigDecimal redTaxAmount = new BigDecimal(redInvoiceRequestParam.getRedTaxAmount());
            redInvoiceRequestDto.setSe(redTaxAmount.negate().setScale(2, RoundingMode.HALF_UP).toString());

            // 3. 处理冲红税率
            BigDecimal redTaxRate = new BigDecimal(redInvoiceRequestParam.getRedTaxRate());
            redInvoiceRequestDto.setSl(redTaxRate.negate().setScale(2, RoundingMode.HALF_UP).toString());
        }
        return redInvoiceRequestDto;
    }

    /**
     * 保存开票记录和商品明细
     */
    private String saveInvoiceRecordAndItem(InvoiceRequestParam param, IvoSellerInfo sellerInfo,
                                            InvoiceRequestDtoOfShuZu requestDto) {
        // 创建发票主表记录
        IvoRecord ivoRecord = new IvoRecord();
        String sellerId = sellerInfo.getSellerId();
        String invoiceTraceId = BizUtil.generateTraceId(sellerId);
        ivoRecord.setInvoiceTraceId(invoiceTraceId);
        ivoRecord.setInvoiceRequestNo(requestDto.getFpqqlsh());
        ivoRecord.setInvoiceType(param.getInvoiceType());
        ivoRecord.setPlatformCode(sellerInfo.getPlatformCode());

        // 设置商户信息 - 优先使用前端传入的值，前端未传入则使用sellerInfo中的值
        ivoRecord.setSellerName(StringUtils.isNotBlank(param.getSellerName()) ?
                param.getSellerName() : sellerInfo.getSellerName());
        ivoRecord.setSellerPhone(StringUtils.isNotBlank(param.getSellerPhone()) ?
                param.getSellerPhone() : sellerInfo.getPhone());
        ivoRecord.setIssuer(sellerInfo.getIssuer());
        ivoRecord.setSellerTaxNumber(sellerInfo.getSellerTaxNumber());
        ivoRecord.setSellerId(sellerInfo.getSellerId());

        // 设置购方信息
        ivoRecord.setBuyerName(param.getBuyerName());
        ivoRecord.setBuyerPhone(param.getBuyerPhone());
        ivoRecord.setBuyerTaxNumber(param.getBuyerTaxNumber());
        ivoRecord.setBuyerAddress(param.getBuyerAddress());
        ivoRecord.setBuyerBankAccount(param.getBuyerBankAccount());

        // 设置发票接收信息
        ivoRecord.setReceiveEmail(param.getReceiveEmail());
        ivoRecord.setReceivePhone(param.getReceivePhone());

        //设置金额相关信息
        // 1. 设置含税标志
        ivoRecord.setIncludeTaxFlag(param.getIncludeTaxFlag());

        // 2. 检查商品税率一致性并获取税率
        BigDecimal totalTaxRate = MathUtil.checkConsistentTaxRate(param.getItemList());
        ivoRecord.setTaxRate(totalTaxRate);

        // 3. 计算含税金额
        BigDecimal includeTaxAmount = MathUtil.calculateTotalAmountWithTax(param.getIncludeTaxFlag(), param.getItemList());
        ivoRecord.setIncludeTaxAmount(includeTaxAmount);

        // 4. 计算不含税金额
        BigDecimal withoutTaxAmount = MathUtil.calculateWithoutTaxAmount(param.getIncludeTaxFlag(), param.getItemList());
        ivoRecord.setWithoutTaxAmount(withoutTaxAmount);

        // 5. 计算税额
        BigDecimal totalTaxAmount = MathUtil.calculateTotalTaxAmount(param.getIncludeTaxFlag(), param.getItemList());
        ivoRecord.setTaxAmount(totalTaxAmount);

        // 设置不动产信息
        if (param.getRealEstateInfo() != null) {
            // 将不动产信息对象转换为JSON字符串
            String realEstateInfoJson = JSONUtil.toJsonStr(param.getRealEstateInfo());
            ivoRecord.setRealEstateInfo(realEstateInfoJson);
        }
        ivoRecord.setInvoiceStatus(InvoiceStatusEnum.PROCESSING.getCode());
        ivoRecord.setCallbackUrl(param.getCallbackUrl());
        ivoRecord.setSpecialTypeCode(param.getSpecialTypeCode());
        ivoRecord.setRemark(param.getRemark());

        // 将InvoiceRequestDtoOfShuZu序列化并存储到request字段中，用于后续重新开票
        try {
            String requestDtoJson = objectMapper.writeValueAsString(requestDto);
            ivoRecord.setRequest(requestDtoJson);
        } catch (Exception e) {
            log.error("序列化请求DTO失败", e);
            // 序列化失败不影响主流程，继续执行
        }
        ivoRecord.setRetryTimes("0");
        ivoRecord.setInvoiceStatus("0");

        ivoRecordMapper.insert(ivoRecord);

        // 创建商品明细列表
        List<IvoItem> itemList = new ArrayList<>();
        for (InvoiceRequestParam.Item paramItem : param.getItemList()) {
            try {
                IvoItem ivoItem = new IvoItem();
                ivoItem.setRecordId(ivoRecord.getId());
                ivoItem.setProductName(paramItem.getProductName());
                ivoItem.setProductCode(paramItem.getProductCode());
                ivoItem.setIncludeTaxFlag(param.getIncludeTaxFlag());

                // 金额
                BigDecimal amount = new BigDecimal(paramItem.getAmount()).setScale(2, RoundingMode.HALF_UP);
                ivoItem.setAmount(amount);

                // 税率
                BigDecimal taxRate = new BigDecimal(paramItem.getTaxRate()).setScale(2, RoundingMode.HALF_UP);
                ivoItem.setTaxRate(taxRate);

                // 税额
                String tax = MathUtil.calculateTax(param.getIncludeTaxFlag(), paramItem.getAmount(), paramItem.getTaxRate());
                BigDecimal taxAmount = new BigDecimal(tax).setScale(2, RoundingMode.HALF_UP);
                ivoItem.setTaxAmount(taxAmount);

                itemList.add(ivoItem);
            } catch (Exception e) {
                log.error("处理商品明细异常，商品名称：{}", paramItem.getProductName(), e);
                // 跳过当前商品继续处理其他商品
            }
        }

        ivoItemService.saveBatch(itemList);
        return invoiceTraceId;
    }

    /**
     * 统一的参数校验方法
     */
    private InvoiceSubmitResultVo validateParam(InvoiceRequestParam param) {
        // 参数校验 - 使用Supplier避免重复代码
        Supplier<InvoiceSubmitResultDto> createErrorResult = InvoiceSubmitResultDto::new;

        if (isEmpty(param.getSellerTaxNumber())) {
            return buildErrorResult(createErrorResult.get(), InvoiceErrorCodeEnum.SELLER_TAX_NUMBER_EMPTY);
        }

        if (isEmpty(param.getBuyerName())) {
            return buildErrorResult(createErrorResult.get(), InvoiceErrorCodeEnum.BUYER_NAME_EMPTY);
        }

        if (param.getItemList() == null || param.getItemList().isEmpty()) {
            return buildErrorResult(createErrorResult.get(), InvoiceErrorCodeEnum.ITEM_LIST_EMPTY);
        }

        // 添加新的严格校验字段
        if (isEmpty(param.getInvoiceType())) {
            return buildErrorResult(createErrorResult.get(), InvoiceErrorCodeEnum.INVOICE_TYPE_EMPTY);
        }

        if (isEmpty(param.getIncludeTaxFlag())) {
            return buildErrorResult(createErrorResult.get(), InvoiceErrorCodeEnum.INCLUDE_TAX_FLAG_EMPTY);
        }

        // 校验商品明细中的字段
        for (InvoiceRequestParam.Item item : param.getItemList()) {
            if (isEmpty(item.getProductName())) {
                return buildErrorResult(createErrorResult.get(), InvoiceErrorCodeEnum.PRODUCT_NAME_EMPTY);
            }

            if (isEmpty(item.getProductCode())) {
                return buildErrorResult(createErrorResult.get(), InvoiceErrorCodeEnum.PRODUCT_CODE_EMPTY);
            }

            if (isEmpty(item.getAmount())) {
                return buildErrorResult(createErrorResult.get(), InvoiceErrorCodeEnum.AMOUNT_EMPTY);
            }

            if (isEmpty(item.getTaxRate())) {
                return buildErrorResult(createErrorResult.get(), InvoiceErrorCodeEnum.TAX_RATE_EMPTY);
            }

        }

        return null; // 校验通过
    }

    /**
     * 构建错误结果
     */
    private InvoiceSubmitResultVo buildErrorResult(InvoiceSubmitResultDto result, InvoiceErrorCodeEnum errorCode) {
        InvoiceSubmitResultVo invoiceSubmitResultVo = BeanUtil.copyProperties(result, InvoiceSubmitResultVo.class);
        invoiceSubmitResultVo.setCode(errorCode.getCode()); // 从布尔值false改为使用错误码枚举的code值
        invoiceSubmitResultVo.setDescription(errorCode.getMsg());
        return invoiceSubmitResultVo;
    }

    /**
     * 检查字符串是否为空
     */
    private boolean isEmpty(String str) {
        return str == null || str.trim().isEmpty();
    }

    /**
     * 转换参数
     */
    private InvoiceRequestDtoOfShuZu convertToShuZuDto(InvoiceRequestParam param, IvoSellerInfo sellerInfo) {
        InvoiceRequestDtoOfShuZu requestDto = new InvoiceRequestDtoOfShuZu();
        requestDto.setSellerId(sellerInfo.getSellerId());
        requestDto.setFpqqlsh(randomFpqqlsh());

        // 基础参数
        requestDto.setFplxdm(param.getInvoiceType()); // 发票类型代码
        requestDto.setHsbz(param.getIncludeTaxFlag()); // 含税标志 0:不含税 1:含税
        requestDto.setTdyslxdm(param.getSpecialTypeCode()); // 特定要素类型代码
        requestDto.setBz(param.getRemark()); // 备注信息

        // 销方信息 - 优先使用param中的值，param中没有则使用sellerInfo中的值
        requestDto.setXfmc(StringUtils.isNotBlank(param.getSellerName()) ?
                param.getSellerName() : sellerInfo.getSellerName()); // 销方名称
        requestDto.setXfsh(sellerInfo.getSellerTaxNumber()); // 销方税号
        requestDto.setXfdz(StringUtils.isNotBlank(param.getSellerAddress()) ?
                param.getSellerAddress() : sellerInfo.getAddress()); // 销方地址
        requestDto.setXflxdh(StringUtils.isNotBlank(param.getSellerPhone()) ?
                param.getSellerPhone() : sellerInfo.getPhone()); // 销方联系方式
        requestDto.setXfyhzh(StringUtils.isNotBlank(param.getSellerBankAccount()) ?
                param.getSellerBankAccount() : sellerInfo.getBankAccount()); // 销方银行账号

        // 购方信息 - 基本信息
        requestDto.setGfmc(param.getBuyerName()); // 购方名称
        requestDto.setGfsh(param.getBuyerTaxNumber()); // 购方税号
        requestDto.setGfdz(param.getBuyerAddress()); // 购方地址
        requestDto.setGflxdh(param.getBuyerPhone()); // 购方联系电话
        requestDto.setGfyhzh(param.getBuyerBankAccount()); // 购方银行账号

        // 发票接收信息 - 用于电子发票发送
        requestDto.setYxdz(param.getReceiveEmail()); // 邮箱地址(发票结果发送)
        requestDto.setSjhm(param.getReceivePhone()); // 手机号码(发票结果发送)

        // 设置不动产经营租赁服务信息
        if (ObjectUtil.isNotEmpty(param.getRealEstateInfo())) {
            InvoiceRequestDtoOfShuZu.bdcjyzlfw bdcjyzlfw = new InvoiceRequestDtoOfShuZu.bdcjyzlfw();
            InvoiceRequestParam.RealEstateInfo realEstateInfo = param.getRealEstateInfo();
            bdcjyzlfw.setFwcqzshm(realEstateInfo.getCertificate()); // 房屋产权证书/不动产权证书号码
            bdcjyzlfw.setBdcdz(realEstateInfo.getAddress()); // 不动产地址
            bdcjyzlfw.setZlqq(realEstateInfo.getStartRentalTime()); // 租赁期起，格式:yyyyMMdd
            bdcjyzlfw.setZlqz(realEstateInfo.getEndRentalTime()); // 租赁期止，格式:yyyyMMdd
            bdcjyzlfw.setKdsbz(realEstateInfo.getCrossCityFlag()); // 跨地市标志，0:否 1:是
            bdcjyzlfw.setMjdw(realEstateInfo.getAreaUnit()); // 面积单位
            requestDto.setBdcjyzlfw(bdcjyzlfw);
        }

        // 转换商品明细列表 - 金额计算交给第三方处理
        List<InvoiceRequestDtoOfShuZu.mxList> dtoMxListList = new ArrayList<>();
        for (InvoiceRequestParam.Item paramItem : param.getItemList()) {
            InvoiceRequestDtoOfShuZu.mxList dtoMxList = new InvoiceRequestDtoOfShuZu.mxList();
            dtoMxList.setSpmc(paramItem.getProductName()); // 商品名称
            dtoMxList.setSpbm(paramItem.getProductCode()); // 商品编码
            dtoMxList.setJe(paramItem.getAmount()); // 含税金额
            dtoMxList.setSl(paramItem.getTaxRate()); // 税率
            String tax = MathUtil.calculateTax(param.getIncludeTaxFlag(), paramItem.getAmount(), paramItem.getTaxRate());
            dtoMxList.setSe(tax); // 税额

            // 处理优惠政策和特殊税率信息
            dtoMxList.setYhzcbs(paramItem.getPreferentialPolicyMark()); // 优惠政策标识
            dtoMxList.setLslbs(paramItem.getZeroTaxRateMark()); // 零税率标识
            if ("5".equals(paramItem.getZeroTaxRateMark())) {
                dtoMxList.setZzstsgl("按5%简易征收"); // 增值税特殊管理标识
            } else {
                dtoMxList.setZzstsgl(null);
            }

            dtoMxListList.add(dtoMxList);
        }
        requestDto.setMxListList(dtoMxListList);

        return requestDto;
    }

    /**
     * 根据销方税号查询抬头信息
     */
    private IvoSellerInfo getSellerInfoByTaxNumber(String sellerTaxNumber) {
        LambdaQueryWrapper<IvoSellerInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(IvoSellerInfo::getSellerTaxNumber, sellerTaxNumber);
        queryWrapper.eq(IvoSellerInfo::getStatus, "1"); // 启用状态
        IvoSellerInfo ivoSellerInfo = ivoSellerInfoMapper.selectOne(queryWrapper);
        return ivoSellerInfo;
    }

    /**
     * 选择合适的开票平台
     */
    private InvoicePlatformEnum selectInvoicePlatform(IvoSellerInfo sellerInfo) {
        // 检查是否指定了平台
        if (sellerInfo.getPlatformCode() == null) {
            throw new InvoiceException(InvoiceErrorCodeEnum.PLATFORM_CODE_EMPTY.getCode(), InvoiceErrorCodeEnum.PLATFORM_CODE_EMPTY.getMsg());
        }

        // 根据平台编码获取对应的枚举
        InvoicePlatformEnum platform = InvoicePlatformEnum.getByCode(sellerInfo.getPlatformCode());
        if (platform == null) {
            throw new InvoiceException(InvoiceErrorCodeEnum.PLATFORM_CODE_INVALID.getCode(),
                    InvoiceErrorCodeEnum.PLATFORM_CODE_INVALID.getMsg() + ":" + sellerInfo.getPlatformCode());
        }

        return platform;
    }


    /**
     * 执行发票状态回调
     *
     * @param ivoRecord 发票记录
     * @param result    发票查询结果
     */
    private void executeCallback(IvoRecord ivoRecord, InvoiceResultDto result) {
        // 检查回调URL是否存在
        if (ivoRecord.getCallbackUrl() == null || ivoRecord.getCallbackUrl().isEmpty()) {
            log.warn("发票ID: {} 回调URL为空，不执行回调", ivoRecord.getId());
            // 更新回调状态为失败
            updateCallbackStatus(ivoRecord, false, 0);
            return;
        }

        // 检查是否已经回调成功
        if ("1".equals(ivoRecord.getCallbacked())) {
            log.info("发票ID: {} 已经回调成功，不再执行回调", ivoRecord.getId());
            return;
        }

        try {
            // 创建回调数据 - 返回完整的InvoiceDetailVo对象
            InvoiceDetailVo callbackData = createCallbackData(ivoRecord, result);
            // 使用Jackson替换Hutool的JSONUtil
            String jsonBody = objectMapper.writeValueAsString(callbackData);

            // 设置请求头
            Map<String, String> headers = new HashMap<>();
            headers.put("Content-Type", "application/json;charset=UTF-8");

            // 发送回调请求
            log.info("执行发票回调，发票ID: {}, 回调URL: {}, 回调数据: {}",
                    ivoRecord.getId(), ivoRecord.getCallbackUrl(), jsonBody);

            String response = HttpUtil.httpRequest(ivoRecord.getCallbackUrl(), jsonBody, headers);
            log.info("发票回调结果，发票ID: {}, 响应: {}", ivoRecord.getId(), response);

            // 解析响应，判断是否回调成功
            boolean callbackSuccess = parseCallbackResponse(response);

            if (callbackSuccess) {
                // 回调成功，从retryCounterMap获取当前重试次数
                int retryCount = 0;
                AtomicInteger counter = retryCounterMap.get(ivoRecord.getId());
                if (counter != null) {
                    retryCount = counter.get();
                }
                // 更新状态，传入重试次数
                updateCallbackStatus(ivoRecord, true, retryCount);
                // 清除重试计数器
                retryCounterMap.remove(ivoRecord.getId());
            } else {
                // 回调失败，准备重试
                handleCallbackRetry(ivoRecord, result);
            }

        } catch (Exception e) {
            log.error("执行发票回调异常，发票ID: {}", ivoRecord.getId(), e);
        }
    }

    /**
     * 解析回调响应，检查是否成功
     *
     * @param response 回调响应字符串
     * @return 是否回调成功（code为0）
     */
    private boolean parseCallbackResponse(String response) {
        try {
            if (response == null || response.trim().isEmpty()) {
                return false;
            }

            JsonNode rootNode = objectMapper.readTree(response);
            // 检查是否有code字段且值为"0"
            if (rootNode.has("code") && "0".equals(rootNode.get("code").asText())) {
                return true;
            }
        } catch (Exception e) {
            log.error("解析回调响应失败: {}", response, e);
        }
        return false;
    }

    /**
     * 处理回调重试
     *
     * @param ivoRecord 发票记录
     * @param result    发票查询结果
     */
    private void handleCallbackRetry(IvoRecord ivoRecord, InvoiceResultDto result) {
        String invoiceId = ivoRecord.getId();

        // 获取当前重试次数，如果不存在则初始化为0
        AtomicInteger retryCount = retryCounterMap.computeIfAbsent(invoiceId, k -> new AtomicInteger(0));
        int currentCount = retryCount.incrementAndGet();

        // 更新发票记录中的重试次数
        ivoRecord.setCallbackTimes(currentCount);

        if (currentCount <= MAX_RETRY_COUNT) {
            log.info("发票回调失败，安排重试，发票ID: {}, 当前重试次数: {}, 最大重试次数: {}",
                    invoiceId, currentCount, MAX_RETRY_COUNT);

            // 异步安排重试 - 修改时间戳为Date对象
            taskScheduler.schedule(() -> {
                try {
                    // 重新获取最新的发票记录
                    IvoRecord latestRecord = ivoRecordService.getById(invoiceId);
                    if (latestRecord != null && !"1".equals(latestRecord.getCallbacked())) {
                        executeCallback(latestRecord, result);
                    } else {
                        log.info("发票已回调成功或不存在，取消重试，发票ID: {}", invoiceId);
                        retryCounterMap.remove(invoiceId);
                    }
                } catch (Exception e) {
                    log.error("执行回调重试失败，发票ID: {}", invoiceId, e);
                }
            }, new Date(System.currentTimeMillis() + RETRY_INTERVAL));
        } else {
            // 达到最大重试次数，更新状态为回调失败
            log.warn("发票回调达到最大重试次数，不再重试，发票ID: {}, 重试次数: {}",
                    invoiceId, currentCount - 1);
            updateCallbackStatus(ivoRecord, false, MAX_RETRY_COUNT);
            retryCounterMap.remove(invoiceId);
        }
    }

    /**
     * 更新回调状态
     *
     * @param ivoRecord 发票记录
     * @param success   是否回调成功
     */
    private void updateCallbackStatus(IvoRecord ivoRecord, boolean success, int times) {
        if (success) {
            ivoRecord.setCallbacked("1"); // 设置为已回调成功
            ivoRecord.setCallbackTimes(times); // 设置回调次数
            log.info("更新发票回调状态成功，发票ID: {}", ivoRecord.getId());
        } else {
            ivoRecord.setCallbacked("0"); // 设置为回调失败
            ivoRecord.setCallbackTimes(times); // 设置回调次数
            log.info("更新发票回调状态为失败，发票ID: {}", ivoRecord.getId());
        }
        // 保存包含重试次数的发票记录
        ivoRecordService.updateById(ivoRecord);
    }

    /**
     * 创建回调数据
     *
     * @param ivoRecord 发票记录
     * @param result    发票查询结果
     * @return 完整的InvoiceDetailVo对象
     */
    private InvoiceDetailVo createCallbackData(IvoRecord ivoRecord, InvoiceResultDto result) {
        // 根据不同的平台使用对应的转换方法
        if ("SHUZU".equals(ivoRecord.getPlatformCode()) && result instanceof InvoiceResultDtoOfShuZU) {
            InvoiceDetailVo vo = InvoiceDetailVo.fromShuZuDto((InvoiceResultDtoOfShuZU) result);
            // 从ivoRecord中获取并设置额外参数
            vo.setInvoicedTraceId(ivoRecord.getInvoiceTraceId());
            vo.setPlatform(Objects.requireNonNull(InvoicePlatformEnum.getByCode(ivoRecord.getPlatformCode())).getCode());
            vo.setInvoiceStatus(Objects.requireNonNull(InvoiceStatusEnum.getByCode(ivoRecord.getInvoiceStatus())).getCode());
            vo.setDescription(result.getMsg());
            return vo;
        } else {
            // 对于未支持的平台，创建一个基础的InvoiceDetailVo
            InvoiceDetailVo vo = new InvoiceDetailVo();
            return vo;
        }
    }

    /**
     * 更新回调状态
     *
     * @param ivoRecord 发票记录
     */
    private void updateCallbackStatus(IvoRecord ivoRecord) {
        ivoRecord.setCallbacked("1"); // 设置为已回调
        ivoRecordService.updateById(ivoRecord);
        log.info("更新发票回调状态成功，发票ID: {}", ivoRecord.getId());
    }

    /**
     * 执行红票回调
     *
     * @param redRecord 红票记录
     * @param result    红票查询结果
     */
    private void executeCallback(RedRecord redRecord, RedInvoiceResultDto result) {
        // 检查回调URL是否存在
        if (redRecord.getCallbackUrl() == null || redRecord.getCallbackUrl().isEmpty()) {
            log.info("红票ID: {} 回调URL为空，使用测试回调接口", redRecord.getId());
            return;
        }

        // 检查是否已经回调成功
        if ("1".equals(redRecord.getCallbacked())) {
            log.info("红票ID: {} 已经回调成功，不再执行回调", redRecord.getId());
            return;
        }

        try {
            // 创建回调数据 - 使用RedInvoiceDetailVo类
            RedInvoiceDetailVo callbackData = RedInvoiceDetailVo.fromShuZuDto((RedInvoiceResultDtoOfShuZu) result);

            // 从redRecord中获取并设置额外参数
            callbackData.setRedInvoiceTraceId(redRecord.getRedInvoiceTraceId());
            callbackData.setPlatform(Objects.requireNonNull(InvoicePlatformEnum.getByCode("SHUZU")).getCode());
            callbackData.setRedInvoiceStatus(redRecord.getStatus());
            callbackData.setDescription(result.getMsg());

            // 使用Jackson将数据序列化为JSON
            String jsonBody = objectMapper.writeValueAsString(callbackData);

            // 设置请求头
            Map<String, String> headers = new HashMap<>();
            headers.put("Content-Type", "application/json;charset=UTF-8");

            // 发送回调请求
            log.info("执行红票回调，红票ID: {}, 回调URL: {}, 回调数据: {}",
                    redRecord.getId(), redRecord.getCallbackUrl(), jsonBody);

            String response = HttpUtil.httpRequest(redRecord.getCallbackUrl(), jsonBody, headers);
            log.info("红票回调结果，红票ID: {}, 响应: {}", redRecord.getId(), response);

            // 解析响应，判断是否回调成功
            boolean callbackSuccess = parseCallbackResponse(response);

            if (callbackSuccess) {
                // 回调成功，从retryCounterMap获取当前重试次数
                int retryCount = 0;
                AtomicInteger counter = retryCounterMap.get(redRecord.getId());
                if (counter != null) {
                    retryCount = counter.get();
                }
                // 更新状态，传入重试次数
                updateRedInvoiceCallbackStatus(redRecord, true, retryCount);
                // 清除重试计数器
                retryCounterMap.remove(redRecord.getId());
            } else {
                // 回调失败，准备重试
                handleRedInvoiceCallbackRetry(redRecord, result);
            }
        } catch (Exception e) {
            log.error("执行红票回调失败，红票ID: {}", redRecord.getId(), e);
            // 异常情况下也进行重试
            handleRedInvoiceCallbackRetry(redRecord, result);
        }
    }

    /**
     * 处理红票回调重试
     *
     * @param redRecord 红票记录
     * @param result    红票查询结果
     */
    private void handleRedInvoiceCallbackRetry(RedRecord redRecord, RedInvoiceResultDto result) {
        String redRecordId = redRecord.getId();

        // 获取当前重试次数，如果不存在则初始化为0
        AtomicInteger retryCount = retryCounterMap.computeIfAbsent(redRecordId, k -> new AtomicInteger(0));
        int currentCount = retryCount.incrementAndGet();

        // 更新红票记录中的重试次数
        redRecord.setCallbackTimes(String.valueOf(currentCount));

        if (currentCount <= MAX_RETRY_COUNT) {
            log.info("红票回调失败，安排重试，红票ID: {}, 当前重试次数: {}, 最大重试次数: {}",
                    redRecordId, currentCount, MAX_RETRY_COUNT);

            // 异步安排重试
            taskScheduler.schedule(() -> {
                try {
                    // 重新获取最新的红票记录
                    RedRecord latestRecord = redRecordService.getById(redRecordId);
                    if (latestRecord != null && !"1".equals(latestRecord.getCallbacked())) {
                        executeCallback(latestRecord, result);
                    } else {
                        log.info("红票已回调成功或不存在，取消重试，红票ID: {}", redRecordId);
                        retryCounterMap.remove(redRecordId);
                    }
                } catch (Exception e) {
                    log.error("执行红票回调重试失败，红票ID: {}", redRecordId, e);
                }
            }, new Date(System.currentTimeMillis() + RETRY_INTERVAL));
        } else {
            // 达到最大重试次数，更新状态为回调失败
            log.warn("红票回调达到最大重试次数，不再重试，红票ID: {}, 重试次数: {}",
                    redRecordId, currentCount - 1);
            updateRedInvoiceCallbackStatus(redRecord, false, MAX_RETRY_COUNT);
            retryCounterMap.remove(redRecordId);
        }
    }

    /**
     * 更新红票回调状态
     *
     * @param redRecord 红票记录
     * @param success   是否回调成功
     * @param times     回调次数
     */
    private void updateRedInvoiceCallbackStatus(RedRecord redRecord, boolean success, int times) {
        if (success) {
            redRecord.setCallbacked("1"); // 设置为已回调成功
            redRecord.setCallbackTimes(String.valueOf(times)); // 设置回调次数
            log.info("更新红票回调状态成功，红票ID: {}", redRecord.getId());
        } else {
            redRecord.setCallbacked("0"); // 设置为回调失败
            redRecord.setCallbackTimes(String.valueOf(times)); // 设置回调次数
            log.info("更新红票回调状态为失败，红票ID: {}", redRecord.getId());
        }
        // 保存包含重试次数的红票记录
        redRecordService.updateById(redRecord);
    }

    /**
     * 处理数族平台的发票查询与更新逻辑
     */
    private void processShuZuPlatformInvoices(List<IvoRecord> shuZuRecords) {
        log.info("开始处理数族平台发票，共{}条记录", shuZuRecords.size());

        InvoicePlatformAdapter instance = InvoicePlatformAdapterFactory.getAdapter(InvoicePlatformEnum.SHUZU.getCode());

        for (IvoRecord ivoRecord : shuZuRecords) {
            String recordId = ivoRecord.getId();
            try {
                log.info("开始查询数族平台发票状态，发票ID：{}", recordId);

                // 数族平台需要循环查询每条发票
                InvoiceResultDtoOfShuZU result = (InvoiceResultDtoOfShuZU) instance.queryInvoiceStatus(
                        ivoRecord.getSellerId(), Collections.singletonList(ivoRecord.getInvoiceRequestNo()));

                // 处理不同的响应结果
                if (ObjectUtil.isEmpty(result)) {
                    log.warn("查询更新发票失败，发票ID：{}", recordId);
                    continue;
                }

                String code = result.getCode();
                if ("0".equals(code)) {
                    // 开票成功
                    ivoRecord.setInvoiceStatus(InvoiceStatusEnum.SUCCESS.getCode());
                    ivoRecord.setFailReason("");
                    ivoRecord.setInvoiceNo(result.getContent().getFphm());
                    ivoRecord.setPdfUrl(result.getContent().getPdfUrl());
                    ivoRecord.setInvoiceDate(result.getContent().getKprq());
                    ivoRecordService.updateById(ivoRecord);
                    log.info("发票开具成功,信息已更新，发票ID：{}", recordId);
                    // 成功状态回调
                    executeCallback(ivoRecord, result);
                } else if ("070004".equals(code)) {
                    // 仍在开票中，不回调
                    executeCallback(ivoRecord, result);
                    log.info("发票仍在处理中，发票ID：{}", recordId);
                } else {
                    // 开票失败
                    ivoRecord.setInvoiceStatus(InvoiceStatusEnum.FAILED.getCode());
                    ivoRecord.setFailReason(result.getMsg());
                    ivoRecordService.updateById(ivoRecord);
                    log.info("发票开具失败,信息已更新，发票ID：{}", recordId);
                    // 失败状态回调
                    executeCallback(ivoRecord, result);
                }
            } catch (Exception e) {
                log.error("查询数族平台发票状态失败，发票ID：{}", recordId, e);
                // 发生异常时不更新发票状态，保持为处理中
            }
        }
    }

    /**
     * 处理诺诺平台的发票查询与更新逻辑
     */
    private void processNuonuoPlatformInvoices(List<IvoRecord> nuonuoRecords) {
        log.info("开始处理诺诺平台发票，共{}条记录", nuonuoRecords.size());

        InvoicePlatformAdapter instance = InvoicePlatformAdapterFactory.getAdapter(InvoicePlatformEnum.NUONUO.getCode());
        if (instance == null) {
            log.error("获取诺诺平台适配器失败");
            return;
        }

        // 诺诺平台的查询逻辑实现
        // 这里根据诺诺平台的具体API和响应格式实现
        // ...
    }

    /**
     * 处理数族平台的红票查询与更新逻辑
     */
    private void processShuZuPlatformRedInvoices(List<RedRecord> shuzuRedInvoices) {
        log.info("开始处理数族平台红票，共{}条记录", shuzuRedInvoices.size());

        InvoicePlatformAdapter instance = InvoicePlatformAdapterFactory.getAdapter(InvoicePlatformEnum.SHUZU.getCode());
        if (ObjectUtil.isEmpty(instance)) {
            log.error("获取数族平台适配器失败");
            return;
        }

        for (RedRecord redRecord : shuzuRedInvoices) {
            String redRecordId = redRecord.getId();
            try {
                String platformCode = redRecord.getPlatformCode();
                String sellerId = redRecord.getSellerId();
                String redInvoiceConfirmId = redRecord.getRedInvoiceConfirmId();

                if (StringUtils.isEmpty(redInvoiceConfirmId) || StringUtils.isEmpty(platformCode) || StringUtils.isEmpty(sellerId)) {
                    log.warn("数族平台红票记录ID: {} 缺少必要信息，跳过查询", redRecordId);
                    continue;
                }

                // 即使是单条查询也使用List入参，便于后续扩展
                RedInvoiceResultDtoOfShuZu result = (RedInvoiceResultDtoOfShuZu) instance.queryRedInvoiceStatus(
                        sellerId, Collections.singletonList(redInvoiceConfirmId));

                // 处理不同的响应结果
                if (ObjectUtil.isEmpty(result)) {
                    log.warn("查询更新红票失败，红票记录ID：{}", redRecordId);
                    continue;
                }

                String code = result.getCode();
                if ("0".equals(code)) {
                    // 红票开具成功
                    redRecord.setStatus("1"); // 成功
                    redRecord.setErrorMessage("");
                    // 设置红票相关信息
                    redRecord.setRedInvoiceDate(result.getContent().getKprq());
                    redRecord.setMxItems(result.getContent().getMxList()); // 明细json
                    redRecord.setPdfUrl(result.getContent().getPdfUrl()); // PDF文件链接
                    redRecord.setOfdUrl(result.getContent().getOfdUrl()); // OFD文件链接
                    redRecord.setXmlUrl(result.getContent().getXmlUrl()); // XML文件链接

                    // 金额信息（转换为BigDecimal）
                    try {
                        if (StringUtils.isNotEmpty(result.getContent().getHjje())) {
                            redRecord.setRedAmount(new BigDecimal(result.getContent().getHjje())); // 合计金额
                        }
                        if (StringUtils.isNotEmpty(result.getContent().getHjse())) {
                            redRecord.setRedTax(new BigDecimal(result.getContent().getHjse())); // 合计税额
                        }
                        if (StringUtils.isNotEmpty(result.getContent().getJshj())) {
                            redRecord.setTotalRedAmount(new BigDecimal(result.getContent().getJshj())); // 价税合计
                        }
                    } catch (NumberFormatException e) {
                        log.error("金额格式转换失败，记录ID: {}", redRecordId, e);
                    }

                    redRecordService.updateById(redRecord);
                    log.info("红票开具成功,信息已更新，红票记录ID：{}, 红票确认单ID: {}, 发票代码: {}, 发票号码: {}",
                            redRecordId, redInvoiceConfirmId,
                            result.getContent().getZzfpdm(), result.getContent().getFphm());
                    // 成功状态回调
                    executeCallback(redRecord, result);
                } else if ("070004".equals(code)) {
                    // 红票仍在处理中，不回调
                    log.info("红票仍在处理中，红票记录ID：{}, 红票确认单ID: {}", redRecordId, redInvoiceConfirmId);
                    executeCallback(redRecord, result);
                } else {
                    // 红票开具失败
                    redRecord.setStatus("2"); // 失败
                    redRecord.setErrorMessage(result.getMsg());
                    redRecordService.updateById(redRecord);
                    log.info("红票开具失败,信息已更新，红票记录ID：{}", redRecordId);
                    // 失败状态回调
                    executeCallback(redRecord, result);
                }
            } catch (Exception e) {
                log.error("查询数族平台红票状态失败，红票记录ID：{}", redRecordId, e);
                // 发生异常时不更新红票状态，保持为处理中
            }
        }
    }

    /**
     * 生成随机发票请求流水号
     */
    private String randomFpqqlsh() {
        StringBuilder sb = new StringBuilder("isvkp");
        for (int i = 0; i < RANDOM_STRING_LENGTH; i++) {
            int index = (int) (RANDOM.nextFloat() * ALLOWED_CHARS.length());
            char randomChar = ALLOWED_CHARS.charAt(index);
            sb.append(randomChar);
        }
        System.out.println("发票交易流水号为:" + sb.toString());
        return sb.toString();
    }
}


